feat(wallet-lib): do not sync transactions if mnemonic is absent#7
Merged
Merged
Conversation
shumkov
pushed a commit
that referenced
this pull request
Nov 23, 2022
feat: type deserialization + encoding
QuantumExplorer
added a commit
that referenced
this pull request
Mar 16, 2026
- Delete fake tests in make_sure_core_is_synced_to_chain_lock/v0 that never called the production method (CRITICAL #1) - Delete fake tests in verify_chain_lock_through_core/v0 that only exercised mock wiring, never the production method (CRITICAL #2) - Add real tree verification in protocol_upgrade tests: v12 now checks shielded pool, notes, nullifiers, and anchors trees (MAJOR #3) - Fix get_contract_with_fetch_info_and_fee assertion to verify the contract is Some, not just Ok (MEDIUM #4) - Rename test_transition_from_version_10 and add actual verification of v11/v12 artifacts (LOW #5) - Replace bare .unwrap() with .expect() in choose_quorum tests (LOW #6) - Remove empty-input smoke test for store_address_balances (LOW #7) - Fix test_decode_state_transition_at_exact_max_size to assert the correct property (not rejected as oversized) rather than incorrectly assuming zeros cannot decode Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 tasks
5 tasks
QuantumExplorer
added a commit
that referenced
this pull request
May 14, 2026
…iagrams New chapter under "Drive" that walks through the bench fixture's widget contract and shows what each count-query proof actually proves — both the path query the prover signs AND the verified element the verifier extracts. Every example is reproducible against the existing bench at `packages/rs-drive/benches/document_count_worst_case.rs`. Seven worked examples (the `group_by = []` proof surface): 1. `(empty)` — primary-key CountTree fast path, 585 B. 2. `brand == X` — PointLookup over byBrand (plain countable), 1,041 B post-v12 (the value-tree-direct shape now activates for any countable terminator, not just rangeCountable). 3. `color == X` — PointLookup over byColor (rangeCountable), 1,327 B. Same shape as #2 — the rangeCountable flag is only relevant for #7. 4. `brand == X AND color == Y` — PointLookup over byBrandColor; the proof descends through the byBrand value tree's `NonCounted`-wrapped `color` continuation to the byBrandColor terminator, 1,911 B. 5. `brand IN [b0, b1]` — outer Keys per In value, no subquery (the value-tree-direct shape on the In axis), 1,102 B. 6. `color IN [c0, c1]` — identical shape to #5, surfacing the v12 generalization at a glance: byBrand (plain countable) and byColor (rangeCountable) produce structurally identical proofs, 1,381 B. 7. `color > floor` — AggregateCountOnRange over byColor's ProvableCountTree; different verifier (`verify_aggregate_count_query`), single u64 result, 2,072 B. Each section has three parts: - **Path query** (decoded path + items + subquery), the prover's spec. - **Verified element / payload** (the structured output of `verify_query`/`verify_aggregate_count_query`). - **Mermaid diagram** with: - The tree element wrapper for the relevant GroveDB subtree. - Blue arrows tracing the descent. - A cyan target node for the verified element. - Faded nodes for context. A "GroveDB Layout" diagram up front shows the storage shape for the whole contract (doctype CountTree primary key, byBrand NormalTree property-name with CountTree value trees and NonCounted-wrapped byBrandColor continuations, byColor ProvableCountTree property-name with CountTree value trees). Each per-query diagram is a focused slice of this overview. An at-a-glance comparison table at the end summarizes primitive choice, verified shape, and proof size across all seven examples to make the structural symmetry between #2/#3 and #5/#6 (post-v12 generalization) and the asymmetry of #7 (AggregateCountOnRange) visually obvious. Registered under `Drive` in `SUMMARY.md` immediately after the existing `Document Count Trees` chapter, which it complements (that chapter explains the tree variants in the abstract; this one shows how queries traverse the resulting layout). Builds cleanly via `mdbook build` against the existing `mdbook-mermaid` preprocessor configuration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
5 tasks
shumkov
added a commit
that referenced
this pull request
May 19, 2026
Five MEDIUM findings batched into a single commit: F6 (correctness) — `submit()` silently no-op'd when the selected recipient address was no longer in `recipientCandidates` (the row flipped to `isUsed = true` between user-tap and submit body). Now surfaces a typed `submitError` so the user sees "the address is no longer available; pick a fresh one" instead of an unresponsive button. F4 (correctness) — IS-rejection branch left the tracked asset-lock status at `InstantSendLocked` even after building a fresh CL proof. If the second `submit_with_cl_height_retry` then failed, the persisted status was stale (CL proof was attached internally but discarded; the row carried the rejected IS proof). The storage explorer + Resume UI both misreported the recovery state. Now calls `advance_asset_lock_status(ChainLocked, Some(chain_proof))` between the upgrade and the second submit so the row accurately reflects the lock's CL-attached state regardless of which way the submit goes. swift-ios #7 — "No funded Core (BIP44 standard) accounts on this wallet" empty-state copy fired even when zero-balance accounts existed. The picker shows all BIP44 standard accounts (incl. zero balance) so the "funded" qualifier was a lie. Dropped it; the picker's balance column tells the user what's spendable. rust-quality #3 — `drive-proof-verifier` Cargo dep was missing `default-features = false`. Consistency with every other path-dep in this crate; harmless today (default feature set is empty) but insulates from upstream feature additions. blockchain-security M2 — `decode_funding_addresses` zero-count short-circuit. The FFI's `slice::from_raw_parts(ptr, 0)` contract is technically sound even with a dangling non-null sentinel, but the explicit early-return makes the safety doc trivially satisfied + skips a function call. Side change: `AssetLockManager::queue_asset_lock_changeset` visibility widened from `pub(super)` to `pub(crate)` so the orchestrated funding flow can pair an `advance_asset_lock_status` call with a flush without going through the asset-lock module boundary. Still crate-private; no consumer-facing API change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 27, 2026
4 tasks
shumkov
added a commit
that referenced
this pull request
Jun 15, 2026
…, contactInfo index allocation (review P0s/Critical) Multi-reviewer pass found three serious bugs in the M3 rotation code that the live UAT missed (UAT only exercised the pending-sent rotation path, which the reject-tombstone masked). All fixed with red→green regression tests. P0 #1 — rotation re-send to an ESTABLISHED contact reset the version to 0. The version bump unmasked the prior sent request's accountReference, but the lookup only consulted `sent_contact_requests` — empty once established (the outgoing request moves into `established_contacts.outgoing_request`). So every real re-key read None, reset version to 0, reproduced the original reference, and was rejected by the contract's `(ownerId, toUserId, accountReference)` unique index. New `ManagedIdentity::prior_sent_account_reference` checks both maps. Test: prior_sent_account_reference_falls_back_to_established_outgoing. P0 #2 — multi-doc sweep thrash. Immutable contactRequest docs are never deleted, so after any accepted rotation a sender has two non-tombstoned docs that BOTH return every sweep. The per-doc dedup compared each against a single tracked reference, so the other doc always triggered apply_rotated — flipping stored state 0↔7, tearing down + rebuilding the external account, and writing changesets every 60s forever. New `newest_received_per_sender` collapses to the newest doc per sender before ingest (a sweep fixpoint); apply_rotated also gains an identical-request idempotency guard. Tests: newest_received_per_sender_collapses_rotated_sender_to_latest_doc, apply_rotated_incoming_request_is_idempotent. Critical (C1) — swallowed persist errors → memory/disk divergence. ~8 state methods mutated in-memory then only logged a store() failure. Worst case: reject() returned Ok even when the tombstone didn't persist → the rejected contact resurrects on next launch with no signal. New PlatformWalletError::Persistence; reject_contact_request and the user-initiated send_payment path now PROPAGATE the error (self-healing sweep writes still log — the immutable on-chain doc / UTXO reconcile re-derives them). Test: reject_propagates_persist_failure (toggle-fail persister, RED→GREEN). Plus: - #6: send-path encryptedPublicKey extraction returns a hard Err instead of a release-no-op debug_assert + zero-fill (would persist a valid-looking all-zero ciphertext if SDK encoding drifts). - #7: contactInfo derivation-index allocated from a high-water mark over ALL owned docs (incl. skipped/undecryptable), not just the decryptable subset — a skipped doc's slot would otherwise collide on the unique index. - #5 (Rust half): set_contact_info returns a 3-state ContactInfoPublishOutcome (Published / DeferredUntilTwoContacts / SkippedWatchOnly) so the UI can stop claiming an unconditional sync. - crypto LOW: documented the account_index/accountReference consistency invariant at the send boundary. 230/230 platform-wallet lib tests green.
shumkov
added a commit
that referenced
this pull request
Jun 23, 2026
…orrect discovery over-scope Spec gains a Q2 status+completion-criteria banner: #1-6 (contact-request flow) done; remaining = #7 contactInfo + discovery ResidentWallet-fallback removal + Swift drain-on-unlock + delete attach_wallet_seed; done-when = git grep empty + builds + testnet on-device acceptance. Corrects the prior over-scoping of discovery: the carry-scalar fix is KEPT (per spec §1/§2/§7), not a rewrite target. TODO gains the Q2 checklist + the out-of-Q2 findings: §6b queue restore (upstream-blocked), §4.2 wipe hardening, §4.8 zero-keys import caveat. auto_accept already tracked separately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov
added a commit
that referenced
this pull request
Jun 23, 2026
Multi-agent review (feasibility/security/scope-dedup/adversarial) corrected two over-optimistic items and added must-fixes: - Discovery: DROP the 'remove ResidentWallet variants' step — it was wrong. External-signable wallets already route through discover_from_master; the ResidentWallet variants are the live path for genuine resident-key wallet TYPES and stay. No library change; the deep verified_scalar-drop rewrite is NOT needed (carry-scalar kept). Fix the §2 'exhaustive' overclaim. - contactInfo (#7) is the load-bearing item: publish must DECRYPT (open), not just seal (doc<->contact binding is in ciphertext); refactor the shared resident-hardcoded fetch helper; build the root path in Rust + pin the parity test to the REAL auth path (silent-undecryptable hazard); high-water FRESH or refuse; implement the ContactInfoDecrypt drain (stub today, testnet-validated); confused-deputy re-validation. - Atomic: wire verify_binds_to_xpub (zero callers) in the SAME change that deletes the dual gate. Port WipingXprv to the sibling FFI (§4.2). Delete the dead dash_sdk_dashpay_* surface. Add negative + cross-device acceptance cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov
added a commit
that referenced
this pull request
Jun 23, 2026
… (Q2 #7) Add contact_info_seal + contact_info_open to ContactCryptoProvider (+ result structs ContactInfoSealed/Opened, re-exported), implemented by the glue over the signer's parity-tested primitives and by the SeedCryptoProvider test harness; UnusedProvider gets stubs (not exercised by its drain test). Security MUST-FIX pinned: the new test contact_info_seal_open_matches_resident_derivation_at_real_auth_path proves the provider's seal/open is byte-identical to the resident derive_contact_info_keys at the REAL identity-auth root path (built via identity_auth_derivation_path_for_type), not an arbitrary test path — contactInfo is self-encrypted, so a wrong root would silently write undecryptable data with no on-chain oracle. The signer derives both hardened-child AES keys in-process (wiped); only ciphertext crosses back. Foundation for the publish/sweep/drain conversion. platform-wallet lib 293/293; platform-wallet-ffi builds clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov
added a commit
that referenced
this pull request
Jun 23, 2026
…(Q2 #7) Convert set_contact_info_with_external_signer to route all key material through ContactCryptoProvider instead of the resident wallet: - split the shared fetch_decrypted_contact_infos into a key-free public scan (fetch_contact_info_docs, single-sourced fetch) + the resident-decrypt wrapper (still used by the signerless sweep); - publish now does find-existing via crypto.contact_info_open (decrypt-to-match, per the review — the doc<->contact binding is in ciphertext) over the public scan, then crypto.contact_info_seal to encrypt; the resident wallet snapshot + derive_contact_info_keys call are gone from publish; - the FFI gains core_signer_handle (ABI break, like send/accept). De-dup (per the user ask): the 4 inline ResolverContactCryptoProvider constructions (send/accept/drain/contactInfo) collapse to one resolver_contact_crypto_provider helper. DecryptedContactInfo trimmed to the fields the sweep actually reads. The sweep still decrypts resident for now (its deferral + the ContactInfoDecrypt drain op is the next step). platform-wallet lib 293/293; glue builds clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov
added a commit
that referenced
this pull request
Jun 23, 2026
…#7) The signerless sweep can't decrypt contactInfo, so sync_contact_infos now branches: a resident-key wallet TYPE decrypts inline (the kept resident path, like discovery's ResidentWallet variant); a seedless/external-signable wallet ENQUEUES a per-owner ContactInfoDecrypt op (idempotent, no payload) for the signer-backed drain. Implement the ContactInfoDecrypt drain op (was a no-op stub): re-fetch the owner's contactInfo docs via the single-sourced key-free scan, decrypt + apply each via the provider's contact_info_open, latest-published-wins. Encapsulated as drain_contact_info_decrypt in contact_info.rs (RawContactInfoDoc stays private there). Security MUST-FIX (review): confused-deputy guard — the drain resolves the entry's owner_identity_id as a wallet-owned identity and errors before any fetch/decrypt if it isn't, so a poisoned entry can't decrypt under the wrong identity. Root path built in Rust. Tests: contact_info_decrypt_drain_rejects_non_owned_identity (the guard) + seedless_sweep_enqueues_contact_info_decrypt (the defer) — both network-free. The full re-fetch+decrypt+apply is testnet-validated (cross-device contactInfo). platform-wallet lib 295/295; glue builds clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shumkov
added a commit
that referenced
this pull request
Jun 23, 2026
… cascade #7 contactInfo seedless (publish + sweep-defer + drain), the discovery no-change confirmation, and the dead dash_sdk_dashpay_* de-dup are DONE this turn. Records the measured §4.9 deletion cascade: removing the make_wallet attach calls fails 5 tests (resident register_contact_account / resident xpub in setup) — the remaining §4.9 work is reworking those onto Wallet-from-seed/ Some + the register_contact_account None-path C3 + the atomic verify_binds_to_xpub wiring + Swift drain-on-unlock. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6 tasks
57 tasks
shumkov
added a commit
that referenced
this pull request
Jul 14, 2026
…st proof assembly Second-pass review fixes on #4041. #1 (blocking): persist the invitation record immediately after funding, BEFORE the InstantSend check — a ChainLock-confirmed voucher is rejected as a *link* but is still a funded, reclaimable lock, so it must be recorded rather than orphaned. My earlier fix put the persist after the IS/CL check, which still orphaned it. #2 (blocking): claim-by-fetch now retries the funding-tx lookup (both byte orders) with a bounded backoff (5 x 3s). InstantSend/ChainLock finality doesn't guarantee the invitee's DAPI node has indexed the tx, so a freshly shared invitation could fail on ordinary propagation lag with no retry. #5: extract the post-fetch proof reconstruction into a pure `assemble_asset_lock_proof` and unit-test its guards (txid mismatch, chainlock-required, chainlock-success, islock-locks-wrong-tx) — previously zero coverage on funds-adjacent logic. #6: `encode_invitation_uri` now rejects a final URI over `MAX_INVITATION_URI_LEN` (percent-encoding can expand fields past the per-field raw cap) — the exact length its own parser enforces, so it can't emit a self-unparseable link. #7: correct the preview FFI `inviter_username` doc — a null username no longer implies has_inviter==false (metadata-only links set has_inviter with a null username). invitation tests: 28/28 (+4 assemble_*) platform-wallet, 10/10 ffi. fmt + clippy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue being fixed or feature implemented
This change eliminates unnecessary synchronization of transactions in case wallet has been generated from the new mnemonic
What was done?
Check if the wallet has been generated from the new mnemonic and sync transactions from the best block (instead of block 1 or the one provided via
unsafeOptions: { skipSynchronizationBeforeHeight: <n> })How Has This Been Tested?
Breaking Changes
Checklist:
For repository code-owners and collaborators only